#include "seamcarvingresize.h"
#include "GraphicsArea/drawingarea.h"
#include "Redimension/redimension.h"


SeamCarvingResize::SeamCarvingResize(DrawingArea* drawing, Layer* layer,
                                     int newWidth, int newHeight) :QThread(drawing)
{
    this->drawing =drawing;
    this->layer = layer;
    this->newWidth = newWidth;
    this->newHeight = newHeight;


}

void SeamCarvingResize::run()
{

    double scaleX = layer->getWidth() / newWidth;
    double scaleY = layer->getHeight() / newHeight;

    if(newWidth > layer->getWidth()){
        increaseX();
    }else if(newWidth < layer->getWidth()){
        decreaseX();
    }

    if(newHeight > layer->getHeight()){
        increaseY();
    }else if(newHeight < layer->getHeight()){
        decreaseY();
    }

    //layer->setSizeBoundingRect(layer->getWidthBoundingRect() * scaleX, layer->getHeightBoundingRect() * scaleY);
    //layer->setPos(layer->x() * scaleX, layer->y() * scaleY);


 }


void SeamCarvingResize::increaseX(){
    cout << "increaseX" << endl;


    SobelFilter* energyFilter = new SobelFilter();

    int numXToDelete = newWidth - layer->getWidth();

    QImage* newImage;
    QImage* sobelImage = new QImage(*layer->getImage());
    energyFilter->filter(sobelImage);

    QImage* imageOriginal = new QImage(*layer->getImage());

    QImage* imageForShow;

    // for the colone
    Seams* seams = new Seams(numXToDelete);


    int sumSeamEnergy = 0;

    int energy;

    Seam* seam;

    Seam*  bestSeam = new Seam(sobelImage->height());
    bestSeam->setSumEnergy(INT_MAX);

    QImage* energyImage = new QImage(*sobelImage);


    for(int i = 0; i < numXToDelete; i++)
    {


        // Creation of the energy for each pixel of the image
        for(int y = 0; y < sobelImage->height(); y++){



            for(int x = 0; x < sobelImage->width(); x++)
            {
                energy = qGray(sobelImage->pixel(x,y));


                // calculation of the energy of the point
                int previousEnergy = INT_MAX;
                if(previousEnergy > qGray(energyImage->pixel(min(max(x - 1, 0),
                                                                 sobelImage->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(x - 1, 0),
                                                                  sobelImage->width() - 1),
                                                              max(y - 1, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(min(max(x, 0),
                                                                 sobelImage->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(x, 0),
                                                                  sobelImage->width() - 1),
                                                              max(y - 1, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(min(max(x + 1, 0),
                                                                 sobelImage->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(x + 1, 0),
                                                                  sobelImage->width() - 1),
                                                              max(y - 1, 0)));
                }

                energy += previousEnergy;
                energy = energy/2;
                energyImage->setPixel(x, y, qRgb(min(energy, 255), min(energy, 255), min(energy, 255)));


            }
        }

        bestSeam =  new Seam(sobelImage->height());
        bestSeam->setSumEnergy(INT_MAX);

        // determination of the best path to multiply
        for(int x = 0; x < sobelImage->width(); x++)
        {

           seam = new Seam(sobelImage->height());




           energy = 0;
           sumSeamEnergy = 0;
           int xCurrent = x;

           for(int y = 0; y < sobelImage->height(); y++){
               //cout << "x : " << x << " currentX = " << xCurrent << endl;

                energy = qGray(energyImage->pixel(xCurrent,y));


                sumSeamEnergy += energy;


                int deplacement;
                int nextEnergy = INT_MAX;

                int energyNextRight = qGray(energyImage->pixel(min(max(xCurrent + 1, 0),
                                                                  energyImage->width() - 1),
                                                              min(y + 1, energyImage->height()-1)));
                int energyNextLeft = qGray(energyImage->pixel(min(max(xCurrent - 1, 0),
                                                                  energyImage->width() - 1),
                                                              min(y + 1, energyImage->height()-1)));
                int energyNextNull = qGray(energyImage->pixel(min(max(xCurrent, 0),
                                                                  energyImage->width() - 1),
                                                              min(y + 1, energyImage->height()-1)));
                if(nextEnergy > energyNextNull)
                {
                    deplacement = 0;
                    nextEnergy = energyNextNull;
                }

                if(nextEnergy > energyNextRight)
                {
                    deplacement = 1;
                    nextEnergy = energyNextRight;
                }

                if(nextEnergy > energyNextLeft)
                {

                    deplacement = -1;
                    nextEnergy = energyNextLeft;
                }


                xCurrent = min(max(xCurrent + deplacement, 0),
                               sobelImage->width() - 1);



                seam->addPoint(xCurrent, y);



            }

           seam->setSumEnergy(sumSeamEnergy);

           //cout << "before deleting"<< endl;
            //cout << "comparason seam < bestSeam " << ((*seam) < (*bestSeam)) << endl;
            if(seam->operator <(*bestSeam)){

                delete bestSeam;

                bestSeam = seam;

            }else{

                delete seam;
                seam = NULL;
            }


        }


        seams->addSeam(bestSeam);

        // change the energy where is the path

        for(int k = 0; k < sobelImage->height(); k++){
            sobelImage->setPixel(*(bestSeam->getPoint(k)), qRgb(255, 255, 255));
        }

        // draw of the path to add
        imageForShow = new QImage(*imageOriginal);
        // recuperation of all the seam.
        priority_queue<Seam*> seamQueue = seams->getSeams();
        while(!seamQueue.empty()){
            Seam* tmpSeam = seamQueue.top();
            seamQueue.pop();
            for(int k = 0; k < energyImage->height(); k++){
                imageForShow->setPixel(*(tmpSeam->getPoint(k)), qRgb(255, 0, 0));;
            }
        }




        layer->setImage(imageForShow);

        drawing->update();


    }


    // redraw the image with the just size
    newImage = new QImage(newWidth, layer->getHeight(),
                          layer->getImage()->format());

    for(int y = 0; y < energyImage->height(); y++){
        QPoint** pointsLine = seams->getPoints(y);

        int x = 0;
        int indicePointsLine = 0;
        int newX = 0;

        QPoint* tmpPoint = pointsLine[indicePointsLine];
        while(indicePointsLine < numXToDelete){
            tmpPoint = pointsLine[indicePointsLine];

            for(int i = x; i <= tmpPoint->x(); i++){
                newImage->setPixel(newX, y,
                                   imageOriginal->pixel(i, y));
                x++;
                newX++;
            }
            newImage->setPixel(newX, y,
                                   imageOriginal->pixel(tmpPoint->x(), y));
            newX++;
            indicePointsLine++;

        }
        for(int i = newX; i < newWidth; i++){
            newImage->setPixel(i, y,
                                   imageOriginal->pixel(tmpPoint->x() + i - newX, y));
        }

    }


    layer->setImage(newImage);


    drawing->update();

}

void SeamCarvingResize::increaseY(){
    SobelFilter* energyFilter = new SobelFilter();

    int numYToDelete = newHeight - layer->getHeight();

    QImage* newImage;
    QImage* sobelImage = new QImage(*layer->getImage());
    energyFilter->filter(sobelImage);

    QImage* imageOriginal = new QImage(*layer->getImage());

    QImage* imageForShow;

    // for the colone
    Seams* seams = new Seams(numYToDelete);


    int sumSeamEnergy = 0;

    int energy;

    Seam* seam;

    Seam*  bestSeam = new Seam(sobelImage->width());
    bestSeam->setSumEnergy(INT_MAX);

    QImage* energyImage = new QImage(*sobelImage);



    for(int i = 0; i < numYToDelete; i++)
    {


        // Creation of the energy for each pixel of the image


        for(int x = 0; x < sobelImage->width(); x++){

           for(int y = 0; y < sobelImage->height(); y++){


                energy = qGray(sobelImage->pixel(x,y));


                // calculation of the energy of the point
                int previousEnergy = INT_MAX;
                if(previousEnergy > qGray(energyImage->pixel(max(x - 1, 0),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(x - 1, 0),
                                                              max(y - 1, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(max(x-1, 0),
                                                             max(y, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(x-1, 0),
                                                              max(y, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(max(x - 1, 0),
                                                             min(y + 1,sobelImage->height()-1))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(x - 1, 0),
                                                              min(y + 1,sobelImage->height()-1)));
                }

                energy += previousEnergy;
                energy = energy/2;
                energyImage->setPixel(x, y, qRgb(min(energy, 255), min(energy, 255), min(energy, 255)));


            }
        }

        bestSeam =  new Seam(sobelImage->width());
        bestSeam->setSumEnergy(INT_MAX);

        // determination of the best path to multiply
       for(int y = 0; y < sobelImage->height(); y++){

           seam = new Seam(sobelImage->width());

           energy = 0;
           sumSeamEnergy = 0;
           int yCurrent = y;

           for(int x = 0; x < sobelImage->width(); x++)
           {

                energy = qGray(energyImage->pixel(x,yCurrent));


                sumSeamEnergy += energy;


                int deplacement;
                int nextEnergy = INT_MAX;

                int energyNextBottom = qGray(energyImage->pixel(min(x + 1, energyImage->width()-1),
                                                             min(max(yCurrent + 1, 0),energyImage->height() - 1)));
                int energyNextTop = qGray(energyImage->pixel(min(x + 1, energyImage->width()-1),
                                                                min(max(yCurrent-1, 0),energyImage->height() - 1)));
                int energyNextNull = qGray(energyImage->pixel(min(x + 1, energyImage->width()-1),
                                                              min(max(yCurrent, 0),energyImage->height() - 1)));
                if(nextEnergy > energyNextNull)
                {
                    deplacement = 0;
                    nextEnergy = energyNextNull;
                }

                if(nextEnergy > energyNextBottom)
                {
                    deplacement = 1;
                    nextEnergy = energyNextBottom;
                }

                if(nextEnergy > energyNextTop)
                {

                    deplacement = -1;
                    nextEnergy = energyNextTop;
                }


                yCurrent = min(max(yCurrent + deplacement, 0),
                               sobelImage->height() - 1);



                seam->addPoint(x,yCurrent);



            }

           seam->setSumEnergy(sumSeamEnergy);


            if(seam->operator <(*bestSeam)){

                delete bestSeam;

                bestSeam = seam;

            }else{

                delete seam;
                seam = NULL;
            }


        }


        seams->addSeam(bestSeam);

        // change the energy where is the path

        for(int k = 0; k < sobelImage->width(); k++){
            sobelImage->setPixel(*(bestSeam->getPoint(k)), qRgb(255, 255, 255));
        }

        // draw of the path to add
        imageForShow = new QImage(*imageOriginal);
        // recuperation of all the seam.
        priority_queue<Seam*> seamQueue = seams->getSeams();
        while(!seamQueue.empty()){
            Seam* tmpSeam = seamQueue.top();
            seamQueue.pop();
            for(int k = 0; k < energyImage->width(); k++){
                imageForShow->setPixel(*(tmpSeam->getPoint(k)), qRgb(255, 0, 0));;
            }
        }


        layer->setImage(imageForShow);


        drawing->update();


    }


    // redraw the image with the just size
    newImage = new QImage(layer->getWidth(), newHeight,
                          layer->getImage()->format());

    for(int x = 0; x< energyImage->width(); x++){
        QPoint** pointsLine = seams->getPoints(x);

        int y = 0;
        int indicePointsLine = 0;
        int newY = 0;

        QPoint* tmpPoint = pointsLine[indicePointsLine];
        while(indicePointsLine < numYToDelete){
            tmpPoint = pointsLine[indicePointsLine];

            for(int i = y; i <= tmpPoint->y(); i++){
                newImage->setPixel(x, newY,
                                   imageOriginal->pixel(x,i));
                y++;
                newY++;
            }
            newImage->setPixel(x, newY,
                                   imageOriginal->pixel(x,tmpPoint->y()));
            newY++;
            indicePointsLine++;

        }
        for(int i = newY; i < newHeight; i++){
            newImage->setPixel(x, i,
                                   imageOriginal->pixel(x, tmpPoint->y() + i - newY));
        }

    }


    layer->setImage(newImage);


    drawing->update();

}

void SeamCarvingResize::decreaseX(){


    QImage* resultat = NULL;

    SobelFilter* energyFilter = new SobelFilter();

    int numXToDelete = layer->getWidth() - newWidth;

    int* seamX ;
    int* seamY;
    int* bestSeamX;
    int* bestSeamY;
    QImage* newImage = new QImage(*layer->getImage());


    for(int i = 0; i < numXToDelete; i++)
    {

        resultat = newImage;

        bestSeamX = new int[resultat->height()];
        bestSeamY = new int[resultat->height()];

        QImage* energyImage = new QImage(*resultat);

        energyFilter->filter(energyImage);

        int sumSeamBestEnergy = INT_MAX;
        int sumSeamEnergy = 0;

        int energy;


        for(int x = 0; x < resultat->width(); x++)
        {

           seamX  = new int[resultat->height()];
           seamY =  new int[resultat->height()];
           seamX[0] = x;
           seamY[0] = 0;

           energy = 0;
           sumSeamEnergy = 0;
           int xCurrent = x;

            for(int y = 0; y < energyImage->height(); y++){

                energy = qGray(energyImage->pixel(xCurrent,y));


                // calculation of the energy of the point
                int previousEnergy = INT_MAX;
                if(previousEnergy > qGray(energyImage->pixel(min(max(xCurrent - 1, 0),
                                                                 resultat->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(xCurrent - 1, 0),
                                                                  resultat->width() - 1),
                                                              max(y - 1, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(min(max(xCurrent, 0),
                                                                 resultat->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(xCurrent, 0),
                                                                  resultat->width() - 1),
                                                              max(y - 1, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(min(max(xCurrent + 1, 0),
                                                                 resultat->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(xCurrent + 1, 0),
                                                                  resultat->width() - 1),
                                                              max(y - 1, 0)));
                }

                energy += previousEnergy;
                sumSeamEnergy += energy;



                int deplacement;
                int nextEnergy = INT_MAX;

                int energyNextRight = qGray(energyImage->pixel(min(max(xCurrent + 1, 0),
                                                                  resultat->width() - 1),
                                                              min(y + 1, resultat->height()-1)));
                int energyNextLeft = qGray(energyImage->pixel(min(max(xCurrent - 1, 0),
                                                                  resultat->width() - 1),
                                                              min(y + 1, resultat->height()-1)));
                int energyNextNull = qGray(energyImage->pixel(min(max(xCurrent, 0),
                                                                  resultat->width() - 1),
                                                              min(y + 1, resultat->height()-1)));
                if(nextEnergy > energyNextNull)
                {
                    deplacement = 0;
                    nextEnergy = energyNextNull;
                }

                if(nextEnergy > energyNextRight)
                {
                    deplacement = 1;
                    nextEnergy = energyNextRight;
                }

                if(nextEnergy > energyNextLeft)
                {

                    deplacement = -1;
                    nextEnergy = energyNextLeft;
                }


                xCurrent = min(max(xCurrent + deplacement, 0),
                               resultat->width() - 1);


                seamX[y] = xCurrent;
                seamY[y] = y;


            }


            if(sumSeamEnergy < sumSeamBestEnergy)
            {
                for(int a = 0; a < resultat->height(); a++)
                {
                    int tmpX = seamX[a];
                    int tmpY = seamY[a];
                    bestSeamX[a] = tmpX;
                    bestSeamY[a] = tmpY;

                }

                sumSeamBestEnergy = sumSeamEnergy;
            }
            delete seamX;
            delete seamY;

        }



        for(int z = 0; z < resultat->height(); z++)
        {
            resultat->setPixel(bestSeamX[z], bestSeamY[z], qRgb(255, 0, 0));
        }


        newImage = new QImage(resultat->width() - 1, resultat->height(),
                              resultat->format());

        int xNewImage = 0;
        for(int yImage = 0; yImage < resultat->height(); yImage++)
        {
            for(int xImage = 0; xImage < resultat->width(); xImage++)
            {

                if(bestSeamX[yImage] != xImage || bestSeamY[yImage] != yImage)
                {
                    newImage->setPixel(xNewImage, yImage,
                                       resultat->pixel(xImage, yImage));
                    xNewImage++;
                }
            }
            xNewImage = 0;
        }


        layer->setImage(resultat);

        drawing->update();
        delete energyImage;
        delete bestSeamX;
        delete bestSeamY;

    }


    layer->setImage(newImage);
    drawing->update();
}

void SeamCarvingResize::decreaseY(){
 QImage* resultat = NULL;

    SobelFilter* energyFilter = new SobelFilter();


    int numYToDelete = layer->getHeight() - newHeight;
    int* seamX ;
    int* seamY;
    int* bestSeamX;
    int* bestSeamY;
    QImage* newImage = new QImage(*layer->getImage());


    for(int i = 0; i < numYToDelete; i++){

        resultat = newImage;

        bestSeamX = new int[resultat->width()];
        bestSeamY = new int[resultat->width()];

        QImage* energyImage = new QImage(*resultat);

        energyFilter->filter(energyImage);

        int sumSeamBestEnergy = INT_MAX;
        int sumSeamEnergy = 0;

        int energy;


        for(int y = 0; y < resultat->height(); y++)
        {

           seamX  = new int[resultat->width()];
           seamY =  new int[resultat->width()];
           seamX[0] = 0;
           seamY[0] = y;

           energy = 0;
           sumSeamEnergy = 0;
           int yCurrent = y;

            for(int x = 0; x < energyImage->width(); x++){

                energy = qGray(energyImage->pixel(x,yCurrent));


                // calculation of the energy of the point
                int previousEnergy = INT_MAX;
                if(previousEnergy > qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent - 1), resultat->height() - 1))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent - 1), resultat->height() - 1)));
                }

                if(previousEnergy > qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent), resultat->height() - 1))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent), resultat->height() - 1)));
                }

                if(previousEnergy > qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent+1), resultat->height() - 1))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent+1), resultat->height() - 1)));
                }

                energy += previousEnergy;
                sumSeamEnergy += energy;

                int deplacement;
                int nextEnergy = INT_MAX;

                int energyNextBottom= qGray(energyImage->pixel(min(x + 1, resultat->width()-1),min(max(yCurrent + 1, 0),resultat->height() - 1)));
                int energyNextTop = qGray(energyImage->pixel(min(x + 1, resultat->width()-1),min(max(yCurrent - 1, 0),resultat->height() - 1)));
                int energyNextNull = qGray(energyImage->pixel(min(x + 1, resultat->width()-1),min(max(yCurrent, 0),resultat->height() - 1)));

                if(nextEnergy > energyNextNull)
                {
                    deplacement = 0;
                    nextEnergy = energyNextNull;
                }

                if(nextEnergy > energyNextBottom)
                {
                    deplacement = 1;
                    nextEnergy = energyNextBottom;
                }

                if(nextEnergy > energyNextTop)
                {

                    deplacement = -1;
                    nextEnergy = energyNextTop;
                }


                yCurrent = min(max(yCurrent + deplacement, 0),
                               resultat->height() - 1);


                seamX[x] = x;
                seamY[x] = yCurrent;


            }


            if(sumSeamEnergy < sumSeamBestEnergy)
            {
                for(int a = 0; a < resultat->width(); a++)
                {
                    int tmpX = seamX[a];
                    int tmpY = seamY[a];
                    bestSeamX[a] = tmpX;
                    bestSeamY[a] = tmpY;

                }

                sumSeamBestEnergy = sumSeamEnergy;
            }
            delete seamX;
            delete seamY;

        }


        for(int z = 0; z < resultat->width(); z++)
        {
            resultat->setPixel(bestSeamX[z], bestSeamY[z], qRgb(255, 0, 0));
        }



        newImage = new QImage(resultat->width(), resultat->height() - 1,
                              resultat->format());

        int yNewImage = 0;
        for(int xImage = 0; xImage < resultat->width(); xImage++)
        {
            for(int yImage = 0; yImage < resultat->height(); yImage++)
            {

                if(bestSeamX[xImage] != xImage || bestSeamY[xImage] != yImage)
                {
                    newImage->setPixel(xImage, yNewImage,
                                       resultat->pixel(xImage, yImage));
                    yNewImage++;
                }
            }
            yNewImage = 0;
        }


        layer->setImage(resultat);

        drawing->update();
        delete energyImage;
        delete bestSeamX;
        delete bestSeamY;


    }


    layer->setImage(newImage);
    drawing->update();

}


/*
void SeamCarvingResize::decreaseX(){
    cout << "decreaseX" << endl;


    SobelFilter* energyFilter = new SobelFilter();

    int numXToDelete = layer->getWidth() - newWidth;

    QImage* newImage;
    QImage* sobelImage = new QImage(*layer->getImage());
    energyFilter->filter(sobelImage);

    QImage* imageOriginal = new QImage(*layer->getImage());

    QImage* imageForShow;

    // for the colone
    Seams* seams = new Seams(numXToDelete);


    int sumSeamEnergy = 0;

    int energy;

    Seam* seam;

    Seam*  bestSeam = new Seam(sobelImage->height());
    bestSeam->setSumEnergy(INT_MAX);

    QImage* energyImage = new QImage(*sobelImage);


    for(int i = 0; i < numXToDelete; i++)
    {


        // Creation of the energy for each pixel of the image
        for(int y = 0; y < sobelImage->height(); y++){



            for(int x = 0; x < sobelImage->width(); x++)
            {
                energy = qGray(sobelImage->pixel(x,y));


                // calculation of the energy of the point
                int previousEnergy = INT_MAX;
                if(previousEnergy > qGray(energyImage->pixel(min(max(x - 1, 0),
                                                                 sobelImage->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(x - 1, 0),
                                                                  sobelImage->width() - 1),
                                                              max(y - 1, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(min(max(x, 0),
                                                                 sobelImage->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(x, 0),
                                                                  sobelImage->width() - 1),
                                                              max(y - 1, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(min(max(x + 1, 0),
                                                                 sobelImage->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(x + 1, 0),
                                                                  sobelImage->width() - 1),
                                                              max(y - 1, 0)));
                }

                energy += previousEnergy;
                energy = energy/2;
                energyImage->setPixel(x, y, qRgb(min(energy, 255), min(energy, 255), min(energy, 255)));


            }
        }

        bestSeam =  new Seam(sobelImage->height());
        bestSeam->setSumEnergy(INT_MAX);

        // determination of the best path to multiply
        for(int x = 0; x < sobelImage->width(); x++)
        {

           seam = new Seam(sobelImage->height());




           energy = 0;
           sumSeamEnergy = 0;
           int xCurrent = x;

           for(int y = 0; y < sobelImage->height(); y++){
               //cout << "x : " << x << " currentX = " << xCurrent << endl;

                energy = qGray(energyImage->pixel(xCurrent,y));


                sumSeamEnergy += energy;


                int deplacement;
                int nextEnergy = INT_MAX;

                int energyNextRight = qGray(energyImage->pixel(min(max(xCurrent + 1, 0),
                                                                  energyImage->width() - 1),
                                                              min(y + 1, energyImage->height()-1)));
                int energyNextLeft = qGray(energyImage->pixel(min(max(xCurrent - 1, 0),
                                                                  energyImage->width() - 1),
                                                              min(y + 1, energyImage->height()-1)));
                int energyNextNull = qGray(energyImage->pixel(min(max(xCurrent, 0),
                                                                  energyImage->width() - 1),
                                                              min(y + 1, energyImage->height()-1)));
                if(nextEnergy > energyNextNull)
                {
                    deplacement = 0;
                    nextEnergy = energyNextNull;
                }

                if(nextEnergy > energyNextRight)
                {
                    deplacement = 1;
                    nextEnergy = energyNextRight;
                }

                if(nextEnergy > energyNextLeft)
                {

                    deplacement = -1;
                    nextEnergy = energyNextLeft;
                }


                xCurrent = min(max(xCurrent + deplacement, 0),
                               sobelImage->width() - 1);



                seam->addPoint(xCurrent, y);



            }

           seam->setSumEnergy(sumSeamEnergy);

           //cout << "before deleting"<< endl;
            //cout << "comparason seam < bestSeam " << ((*seam) < (*bestSeam)) << endl;
            if(seam->operator <(*bestSeam)){

                delete bestSeam;

                bestSeam = seam;

            }else{

                delete seam;
                seam = NULL;
            }


        }


        seams->addSeam(bestSeam);

        // change the energy where is the path

        for(int k = 0; k < sobelImage->height(); k++){
            sobelImage->setPixel(*(bestSeam->getPoint(k)), qRgb(255, 255, 255));
        }

        // draw of the path to add
        imageForShow = new QImage(*imageOriginal);
        // recuperation of all the seam.
        priority_queue<Seam*> seamQueue = seams->getSeams();
        while(!seamQueue.empty()){
            Seam* tmpSeam = seamQueue.top();
            seamQueue.pop();
            for(int k = 0; k < energyImage->height(); k++){
                imageForShow->setPixel(*(tmpSeam->getPoint(k)), qRgb(255, 0, 0));;
            }
        }




        layer->setImage(imageForShow);

        drawing->update();


    }


    // redraw the image with the just size
    newImage = new QImage(newWidth, layer->getHeight(),
                          layer->getImage()->format());

    for(int y = 0; y < energyImage->height(); y++){
        QPoint** pointsLine = seams->getPoints(y);

        int x = 0;
        int indicePointsLine = 0;
        int newX = 0;

        QPoint* tmpPoint = pointsLine[indicePointsLine];
        while(indicePointsLine < numXToDelete){
            tmpPoint = pointsLine[indicePointsLine];

            for(int i = x; i < tmpPoint->x(); i++){

                    newImage->setPixel(newX, y,
                                       imageOriginal->pixel(i, y));
                    x++;
                    newX++;

            }
            newImage->setPixel(newX, y,
                                   imageOriginal->pixel(tmpPoint->x(), y));
            newX++;
            indicePointsLine++;

        }
        for(int i = newX; i < newWidth; i++){
            newImage->setPixel(i, y,
                                   imageOriginal->pixel(tmpPoint->x() + i - newX, y));
        }


    }


    layer->setImage(newImage);


    drawing->update();

}

void SeamCarvingResize::decreaseY(){
    SobelFilter* energyFilter = new SobelFilter();

    int numYToDelete = layer->getHeight() - newHeight;

    QImage* newImage;
    QImage* sobelImage = new QImage(*layer->getImage());
    energyFilter->filter(sobelImage);

    QImage* imageOriginal = new QImage(*layer->getImage());

    QImage* imageForShow;

    // for the colone
    Seams* seams = new Seams(numYToDelete);


    int sumSeamEnergy = 0;

    int energy;

    Seam* seam;

    Seam*  bestSeam = new Seam(sobelImage->width());
    bestSeam->setSumEnergy(INT_MAX);

    QImage* energyImage = new QImage(*sobelImage);



    for(int i = 0; i < numYToDelete; i++)
    {


        // Creation of the energy for each pixel of the image


        for(int x = 0; x < sobelImage->width(); x++){

           for(int y = 0; y < sobelImage->height(); y++){


                energy = qGray(sobelImage->pixel(x,y));


                // calculation of the energy of the point
                int previousEnergy = INT_MAX;
                if(previousEnergy > qGray(energyImage->pixel(max(x - 1, 0),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(x - 1, 0),
                                                              max(y - 1, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(max(x-1, 0),
                                                             max(y, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(x-1, 0),
                                                              max(y, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(max(x - 1, 0),
                                                             min(y + 1,sobelImage->height()-1))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(x - 1, 0),
                                                              min(y + 1,sobelImage->height()-1)));
                }

                energy += previousEnergy;
                energy = energy/2;
                energyImage->setPixel(x, y, qRgb(min(energy, 255), min(energy, 255), min(energy, 255)));


            }
        }

        bestSeam =  new Seam(sobelImage->width());
        bestSeam->setSumEnergy(INT_MAX);

        // determination of the best path to multiply
       for(int y = 0; y < sobelImage->height(); y++){

           seam = new Seam(sobelImage->width());

           energy = 0;
           sumSeamEnergy = 0;
           int yCurrent = y;

           for(int x = 0; x < sobelImage->width(); x++)
           {

                energy = qGray(energyImage->pixel(x,yCurrent));


                sumSeamEnergy += energy;


                int deplacement;
                int nextEnergy = INT_MAX;

                int energyNextBottom = qGray(energyImage->pixel(min(x + 1, energyImage->width()-1),
                                                             min(max(yCurrent + 1, 0),energyImage->height() - 1)));
                int energyNextTop = qGray(energyImage->pixel(min(x + 1, energyImage->width()-1),
                                                                min(max(yCurrent-1, 0),energyImage->height() - 1)));
                int energyNextNull = qGray(energyImage->pixel(min(x + 1, energyImage->width()-1),
                                                              min(max(yCurrent, 0),energyImage->height() - 1)));
                if(nextEnergy > energyNextNull)
                {
                    deplacement = 0;
                    nextEnergy = energyNextNull;
                }

                if(nextEnergy > energyNextBottom)
                {
                    deplacement = 1;
                    nextEnergy = energyNextBottom;
                }

                if(nextEnergy > energyNextTop)
                {

                    deplacement = -1;
                    nextEnergy = energyNextTop;
                }


                yCurrent = min(max(yCurrent + deplacement, 0),
                               sobelImage->height() - 1);



                seam->addPoint(x,yCurrent);



            }

           seam->setSumEnergy(sumSeamEnergy);

            cout << "avant comparaison" << endl;
            if(seam->operator <(*bestSeam))){//&& !seams->addNotPossible(seam)
                cout << "in comparaison " << endl;
                delete bestSeam;

                bestSeam = seam;

            }else{

                delete seam;
                seam = NULL;
            }
            cout << "apres comparaison" << endl;

        }

        cout << "avant addbestseam " << bestSeam->getPoint(0)->x() << endl;
        seams->addSeam(bestSeam);


        // change the energy where is the path
        cout << "avant draw image" << endl;
        for(int k = 0; k < sobelImage->width(); k++){
            sobelImage->setPixel(*(bestSeam->getPoint(k)), qRgb(255, 255, 255));
        }

        // draw of the path to add
        imageForShow = new QImage(*imageOriginal);
        // recuperation of all the seam.
        priority_queue<Seam*> seamQueue = seams->getSeams();
        while(!seamQueue.empty()){
            Seam* tmpSeam = seamQueue.top();
            seamQueue.pop();
            for(int k = 0; k < energyImage->width(); k++){
                imageForShow->setPixel(*(tmpSeam->getPoint(k)), qRgb(255, 0, 0));;
            }
        }

        cout << "avant set image" << endl;
        layer->setImage(imageForShow);


        drawing->update();


    }


    // redraw the image with the just size
    newImage = new QImage(layer->getWidth(), newHeight,
                          layer->getImage()->format());

    for(int x = 0; x< energyImage->width(); x++){
        QPoint** pointsLine = seams->getPoints(x);

        int y = 0;
        int indicePointsLine = 0;
        int newY = 0;


        QPoint* tmpPoint = pointsLine[indicePointsLine];
        while(indicePointsLine < numYToDelete){
            tmpPoint = pointsLine[indicePointsLine];

            for(int i = y; i < tmpPoint->y(); i++){
                newImage->setPixel(x, newY,
                                   imageOriginal->pixel(x,i));
                y++;
                newY++;
            }

            y++;
            indicePointsLine++;

        }
        for(int i = newY; i < newHeight; i++){
            newImage->setPixel(x, i,
                                   imageOriginal->pixel(x, tmpPoint->y() + i - newY));
        }

    }


    layer->setImage(newImage);


    drawing->update();
}
*/

void SeamCarvingResize::decrease()
{


    QImage* resultat = NULL;

    SobelFilter* energyFilter = new SobelFilter();

    int numXToDelete = layer->getWidth() - newWidth;
    int numYToDelete = layer->getHeight() - newHeight;
    int* seamX ;
    int* seamY;
    int* bestSeamX;
    int* bestSeamY;
    QImage* newImage = new QImage(*layer->getImage());


    for(int i = 0; i < numXToDelete; i++)
    {

        resultat = newImage;

        bestSeamX = new int[resultat->height()];
        bestSeamY = new int[resultat->height()];

        QImage* energyImage = new QImage(*resultat);

        energyFilter->filter(energyImage);

        int sumSeamBestEnergy = INT_MAX;
        int sumSeamEnergy = 0;

        int energy;


        for(int x = 0; x < resultat->width(); x++)
        {

           seamX  = new int[resultat->height()];
           seamY =  new int[resultat->height()];
           seamX[0] = x;
           seamY[0] = 0;

           energy = 0;
           sumSeamEnergy = 0;
           int xCurrent = x;

            for(int y = 0; y < energyImage->height(); y++){

                energy = qGray(energyImage->pixel(xCurrent,y));


                // calculation of the energy of the point
                int previousEnergy = INT_MAX;
                if(previousEnergy > qGray(energyImage->pixel(min(max(xCurrent - 1, 0),
                                                                 resultat->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(xCurrent - 1, 0),
                                                                  resultat->width() - 1),
                                                              max(y - 1, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(min(max(xCurrent, 0),
                                                                 resultat->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(xCurrent, 0),
                                                                  resultat->width() - 1),
                                                              max(y - 1, 0)));
                }

                if(previousEnergy > qGray(energyImage->pixel(min(max(xCurrent + 1, 0),
                                                                 resultat->width() - 1),
                                                             max(y - 1, 0))))
                {
                    previousEnergy = qGray(energyImage->pixel(min(max(xCurrent + 1, 0),
                                                                  resultat->width() - 1),
                                                              max(y - 1, 0)));
                }

                energy += previousEnergy;
                sumSeamEnergy += energy;



                int deplacement;
                int nextEnergy = INT_MAX;

                int energyNextRight = qGray(energyImage->pixel(min(max(xCurrent + 1, 0),
                                                                  resultat->width() - 1),
                                                              min(y + 1, resultat->height()-1)));
                int energyNextLeft = qGray(energyImage->pixel(min(max(xCurrent - 1, 0),
                                                                  resultat->width() - 1),
                                                              min(y + 1, resultat->height()-1)));
                int energyNextNull = qGray(energyImage->pixel(min(max(xCurrent, 0),
                                                                  resultat->width() - 1),
                                                              min(y + 1, resultat->height()-1)));
                if(nextEnergy > energyNextNull)
                {
                    deplacement = 0;
                    nextEnergy = energyNextNull;
                }

                if(nextEnergy > energyNextRight)
                {
                    deplacement = 1;
                    nextEnergy = energyNextRight;
                }

                if(nextEnergy > energyNextLeft)
                {

                    deplacement = -1;
                    nextEnergy = energyNextLeft;
                }


                xCurrent = min(max(xCurrent + deplacement, 0),
                               resultat->width() - 1);


                seamX[y] = xCurrent;
                seamY[y] = y;


            }


            if(sumSeamEnergy < sumSeamBestEnergy)
            {
                for(int a = 0; a < resultat->height(); a++)
                {
                    int tmpX = seamX[a];
                    int tmpY = seamY[a];
                    bestSeamX[a] = tmpX;
                    bestSeamY[a] = tmpY;

                }

                sumSeamBestEnergy = sumSeamEnergy;
            }
            delete seamX;
            delete seamY;

        }



        for(int z = 0; z < resultat->height(); z++)
        {
            resultat->setPixel(bestSeamX[z], bestSeamY[z], qRgb(255, 0, 0));
        }


        newImage = new QImage(resultat->width() - 1, resultat->height(),
                              resultat->format());

        int xNewImage = 0;
        for(int yImage = 0; yImage < resultat->height(); yImage++)
        {
            for(int xImage = 0; xImage < resultat->width(); xImage++)
            {

                if(bestSeamX[yImage] != xImage || bestSeamY[yImage] != yImage)
                {
                    newImage->setPixel(xNewImage, yImage,
                                       resultat->pixel(xImage, yImage));
                    xNewImage++;
                }
            }
            xNewImage = 0;
        }


        layer->setImage(resultat);

        drawing->update();
        delete energyImage;
        delete bestSeamX;
        delete bestSeamY;

    }

    for(int i = 0; i < numYToDelete; i++){

        resultat = newImage;

        bestSeamX = new int[resultat->width()];
        bestSeamY = new int[resultat->width()];

        QImage* energyImage = new QImage(*resultat);

        energyFilter->filter(energyImage);

        int sumSeamBestEnergy = INT_MAX;
        int sumSeamEnergy = 0;

        int energy;


        for(int y = 0; y < resultat->height(); y++)
        {

           seamX  = new int[resultat->width()];
           seamY =  new int[resultat->width()];
           seamX[0] = 0;
           seamY[0] = y;

           energy = 0;
           sumSeamEnergy = 0;
           int yCurrent = y;

            for(int x = 0; x < energyImage->width(); x++){

                energy = qGray(energyImage->pixel(x,yCurrent));


                // calculation of the energy of the point
                int previousEnergy = INT_MAX;
                if(previousEnergy > qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent - 1), resultat->height() - 1))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent - 1), resultat->height() - 1)));
                }

                if(previousEnergy > qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent), resultat->height() - 1))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent), resultat->height() - 1)));
                }

                if(previousEnergy > qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent+1), resultat->height() - 1))))
                {
                    previousEnergy = qGray(energyImage->pixel(max(0,x-1), min(max(0,yCurrent+1), resultat->height() - 1)));
                }

                energy += previousEnergy;
                sumSeamEnergy += energy;

                int deplacement;
                int nextEnergy = INT_MAX;

                int energyNextBottom= qGray(energyImage->pixel(min(x + 1, resultat->width()-1),min(max(yCurrent + 1, 0),resultat->height() - 1)));
                int energyNextTop = qGray(energyImage->pixel(min(x + 1, resultat->width()-1),min(max(yCurrent - 1, 0),resultat->height() - 1)));
                int energyNextNull = qGray(energyImage->pixel(min(x + 1, resultat->width()-1),min(max(yCurrent, 0),resultat->height() - 1)));

                if(nextEnergy > energyNextNull)
                {
                    deplacement = 0;
                    nextEnergy = energyNextNull;
                }

                if(nextEnergy > energyNextBottom)
                {
                    deplacement = 1;
                    nextEnergy = energyNextBottom;
                }

                if(nextEnergy > energyNextTop)
                {

                    deplacement = -1;
                    nextEnergy = energyNextTop;
                }


                yCurrent = min(max(yCurrent + deplacement, 0),
                               resultat->height() - 1);


                seamX[x] = x;
                seamY[x] = yCurrent;


            }


            if(sumSeamEnergy < sumSeamBestEnergy)
            {
                for(int a = 0; a < resultat->width(); a++)
                {
                    int tmpX = seamX[a];
                    int tmpY = seamY[a];
                    bestSeamX[a] = tmpX;
                    bestSeamY[a] = tmpY;

                }

                sumSeamBestEnergy = sumSeamEnergy;
            }
            delete seamX;
            delete seamY;

        }


        for(int z = 0; z < resultat->width(); z++)
        {
            resultat->setPixel(bestSeamX[z], bestSeamY[z], qRgb(255, 0, 0));
        }



        newImage = new QImage(resultat->width(), resultat->height() - 1,
                              resultat->format());

        int yNewImage = 0;
        for(int xImage = 0; xImage < resultat->width(); xImage++)
        {
            for(int yImage = 0; yImage < resultat->height(); yImage++)
            {

                if(bestSeamX[xImage] != xImage || bestSeamY[xImage] != yImage)
                {
                    newImage->setPixel(xImage, yNewImage,
                                       resultat->pixel(xImage, yImage));
                    yNewImage++;
                }
            }
            yNewImage = 0;
        }


        layer->setImage(resultat);

        drawing->update();
        delete energyImage;
        delete bestSeamX;
        delete bestSeamY;


    }


    layer->setImage(newImage);
    drawing->update();

}

